#include"SPI.h"

bool _choose234(uint8_t SPIx)
{
    if(SPIx == SPI2)
    {
        USXINX = USCI2;
    }
    else if(SPIx == SPI3)
    {
        USXINX = USCI3;
    }
    else if(SPIx == SPI4)
    {
        USXINX = USCI4;
    }
    else return false;
    return true;
}

/**
 * @brief 设置发送位数
 * 
 * @param SPIx: SPI0, 1, 2, 3, 4
 * @param size: SPMD_bit8 或 SPMD_bit16
 */
void SPI_setSize(uint8_t SPIx, uint8_t size)
{
    if(SPIx == SPI0)
    {
        CLEAR_BIT(US0CON1, SPMD);
        SET_BIT(US0CON1, size);
    }
    else if(SPIx == SPI1)
    {
        CLEAR_BIT(US1CON1, SPMD);
        SET_BIT(US1CON1, size);
    }
    else
    {
        if(!_choose234(SPIx)) return;
        CLEAR_BIT(USXCON1, SPMD);
        SET_BIT(USXCON1, size);
    }
}

/**
 * @brief SPI 默认初始化: 芯片作主设备, 频率为fsys/128, 一次传输16位数据
 * SCK 空闲低电平, 上升沿采样
 * 
 * @param SPIx x=0,1,2,3,4
 */
void SPI_init(uint8_t SPIx)
{
    if(SPIx == SPI0)
    {
        CLEAR_BIT(OTCON, USMD0);
        SET_BIT(OTCON, BIT(4));
        // CON0
        SET_BIT(US0CON0, 0 | MSTR);
        CLEAR_BIT(US0CON0, CPOL | CPHA);
        CLEAR_BIT(US0CON0, SPR);
        SET_BIT(US0CON0, SPR_FSYS128);
        // CON1
        SET_BIT(US0CON1, SPMD);
        CLEAR_BIT(US0CON1, SPIF | WCOL | DORD | TBIE);
    }
    else if(SPIx == SPI1)
    {
        CLEAR_BIT(OTCON, USMD1);
        SET_BIT(OTCON, BIT(6));
        // CON0
        SET_BIT(US1CON0, 0 | MSTR);
        CLEAR_BIT(US1CON0, CPOL | CPHA);
        CLEAR_BIT(US1CON0, SPR);
        SET_BIT(US1CON0, SPR_FSYS128);
        // CON1
        SET_BIT(US1CON1, SPMD);
        CLEAR_BIT(US1CON1, SPIF | WCOL | DORD | TBIE);
    }
    else
    {
        if(SPIx == SPI2)
        {
            CLEAR_BIT(TMCON, USMD2);
            SET_BIT(TMCON, BIT(6));
            USXINX = USCI2;
        }
        else if(SPIx == SPI3)
        {
            CLEAR_BIT(TMCON, USMD3);
            SET_BIT(TMCON, BIT(4));
            USXINX = USCI3;
        }
        else if(SPIx == SPI4)
        {
            CLEAR_BIT(TMCON, USMD4);
            SET_BIT(TMCON, BIT(2));
            USXINX = USCI4;
        }
        // CON0
        SET_BIT(USXCON0, 0 | MSTR);
        CLEAR_BIT(USXCON0, CPOL | CPHA);
        CLEAR_BIT(USXCON0, SPR);
        SET_BIT(USXCON0, SPR_FSYS128);
        // CON1
        SET_BIT(USXCON1, SPMD);
        CLEAR_BIT(USXCON1, SPIF | WCOL | DORD | TBIE);
    }
}

/**
 * @brief 开始发送数据
 * 
 * @param SPIx x=0,1,2,3,4
 */
void SPI_begin(uint8_t SPIx)
{
    if(SPIx == SPI0)
    {
        SET_BIT(US0CON0, SPEN);
    }
    else if(SPIx == SPI1)
    {
        SET_BIT(US1CON0, SPEN);
    }
    else
    {
        if(!_choose234(SPIx)) return;
        SET_BIT(USXCON0, SPEN);
    }
}

/**
 * @brief 读取完成发送标志位
 * 
 * @param SPIx 
 * @return true 
 * @return false 
 */
bool SPI_sendFinish(uint8_t SPIx)
{
    bool result = false;
    if(SPIx == SPI0)
    {
        result = IS_BIT_1(US0CON1, SPIF);
    }
    else if(SPIx == SPI1)
    {
        result = IS_BIT_1(US1CON1, SPIF);
    }
    else
    {
        if(!_choose234(SPIx)) return false;
        result = IS_BIT_1(USXCON1, SPIF);
    }
    return result;
}

/**
 * @brief 发送字(16位数据)
 * 
 * @param SPIx x=0,1,2,3,4
 * @param word 要发送的数据
 */
void SPI_sendWord(uint8_t SPIx, uint16_t word)
{
    uint8_t temp0 = word & 0xFF;
    uint8_t temp1 = word >> 8;
    if(SPIx == SPI0)
    {
        US0CON3 = temp1;
        US0CON2 = temp0;
    }
    else if(SPIx == SPI1)
    {
        US1CON3 = temp1;
        US1CON2 = temp0;
    }
    else
    {
        if(!_choose234(SPIx)) return;
        USXCON3 = temp1;
        USXCON2 = temp0;
    }
}

/**
 * @brief 接收字(16位数据)
 * 
 * @param SPIx x=0,1,2,3,4
 * @return uint16_t 接收到的字
 */
uint16_t SPI_receiveWord(uint8_t SPIx)
{
    uint16_t temp = 0;
    if(SPIx == SPI0)
    {
        if(IS_BIT_1(US0CON1, SPIF))
        {
            temp = (US0CON3<<8) | US0CON2;
            return temp;
        }
    }
    else if(SPIx == SPI1)
    {
        if(IS_BIT_1(US1CON1, SPIF))
        {
            temp = (US1CON3<<8) | US1CON2;
            return temp;
        }
    }
    else
    {
        if(!_choose234(SPIx)) return 0;
        if(IS_BIT_1(USXCON1, SPIF))
        {
            temp = (USXCON3<<8) | USXCON2;
            return temp;
        }
    }
}

/**
 * @brief 清除完成发送标志位
 * 
 * @param SPIx x=0,1,2,3,4
 */
void SPI_clearFlag(uint8_t SPIx)
{
    if(SPIx == SPI0)
    {
        CLEAR_BIT(US0CON1, SPIF);
    }
    else if(SPIx == SPI1)
    {
        CLEAR_BIT(US1CON1, SPIF);
    }
    else
    {
        if(!_choose234(SPIx)) return;
        CLEAR_BIT(USXCON1, SPIF);
    }
}

/**
 * @brief 结束发送
 * 
 * @param SPIx 
 */
void SPI_end(uint8_t SPIx)
{
    if(SPIx == SPI0)
    {
        CLEAR_BIT(US0CON0, SPEN);
    }
    else if(SPIx == SPI1)
    {
        CLEAR_BIT(US1CON0, SPEN);
    }
    else
    {
        if(!_choose234(SPIx)) return;
        CLEAR_BIT(USXCON0, SPEN);
    }
}
